import base64

from PySide2.QtCore import Qt, Signal, Slot, QTimer, QDateTime
from PySide2.QtGui import QPixmap, QImage
from PySide2.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QTextEdit,
    QLineEdit, QPushButton, QScrollArea, QSizePolicy, QFrame, QFileDialog
)
import json
import os
import sys

from qfluentwidgets import FluentIcon, PushButton

class MessageBubble(QWidget):
    """
    消息气泡类
    """

    def __init__(self, is_outgoing, avatar_path, message, timestamp, parent=None):
        super().__init__(parent)
        self.is_outgoing = int(is_outgoing)  # 标记消息是否为发出的
        layout = QHBoxLayout()
        self.setLayout(layout)

        # 左侧显示顺序 【头像 消息 时间】
        # 右侧显示顺序 【时间 消息 头像】

        # 头像
        avatar_label = QLabel(self)
        if is_outgoing:
            pixmap = QPixmap(QImage.fromData(avatar_path))
        elif not is_outgoing:
            if avatar_path and os.path.exists(avatar_path) and os.path.getsize(avatar_path) > 0:
                pixmap = QPixmap(avatar_path)
            else:
                avatar_data = ''
                avatar_path = base64.b64decode(avatar_data.split(',')[1])
                pixmap = QPixmap(QImage.fromData(avatar_path))
        avatar_label.setPixmap(pixmap.scaled(40, 40))

        # 消息
        if not message.startswith('file:///'):
            message_label = QLabel(message)
            message_label.setWordWrap(True)
            message_label.setStyleSheet(
                "QLabel {"
                "   background-color: rg(255,255,255); "
                "   border-radius: 10px; "
                "   padding: 10px; "
                "   color: black;"
                "}"
            )
        elif message.startswith('file:///'):
            file_path = message.lstrip('file:///')
            if file_path.endswith('.jpg') or file_path.endswith('.png') or file_path.endswith(
                    '.jpeg') or file_path.endswith('.JPG') or file_path.endswith('.JPEG') or file_path.endswith('.PNG'):
                # 如果是图片路径
                try:
                    message_pixmap = QPixmap(file_path)
                    message_label = QLabel(self)
                    message_label.setPixmap(message_pixmap.scaledToWidth(200, Qt.SmoothTransformation))
                except:  # 路径下已找不到图片位置，直接显示文字
                    message = "[图片]"
                    message_label = QLabel(message)
                    message_label.setWordWrap(True)
                    message_label.setStyleSheet(
                        "QLabel {"
                        "   background-color: rg(255,255,255); "
                        "   border-radius: 10px; "
                        "   padding: 10px; "
                        "   color: black;"
                        "}"
                    )
            else:
                message = "[文件消息，请在手机微信查看]"
                message_label = QLabel(message)
                message_label.setWordWrap(True)
                message_label.setStyleSheet(
                    "QLabel {"
                    "   background-color: rg(255,255,255); "
                    "   border-radius: 10px; "
                    "   padding: 10px; "
                    "   color: black;"
                    "}"
                )

        # 时间戳
        timestamp_label = QLabel(timestamp)
        timestamp_label.setStyleSheet("font-size: 10pt; color: gray;")

        if self.is_outgoing == 0:  # 接收消息，显示在左侧
            # 设置消息气泡颜色
            message_label.setStyleSheet(
                "QLabel {"
                "   background-color: rgb(255,255,255); "
                "   border-radius: 10px; "
                "   padding: 10px; "
                "   color: black;"
                "}"
            )
            layout.addWidget(avatar_label)  # 添加头像
            layout.addWidget(message_label)  # 添加消息
            layout.addWidget(timestamp_label)  # 添加时间戳
            layout.addStretch()
        elif self.is_outgoing == 1:  # 发送消息，显示在右侧
            # 设置消息气泡颜色
            message_label.setStyleSheet(
                "QLabel {"
                "   background-color: rgb(149,236,105); "
                "   border-radius: 10px; "
                "   padding: 10px; "
                "   color: black;"
                "}"
            )
            layout.addStretch()
            layout.addWidget(timestamp_label)  # 添加时间戳
            # message_label.setAlignment(Qt.AlignRight)
            layout.addWidget(message_label)  # 添加消息
            layout.addWidget(avatar_label)  # 添加头像

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)


class MsgInput(QWidget):
    message_sent = Signal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        layout = QVBoxLayout()
        layout.setSpacing(0)
        self.setLayout(layout)

        # 设置背景颜色
        self.setStyleSheet("background-color: rgb(245, 245, 245);")

        # 输入框
        self.input_field = QTextEdit()
        self.input_field.setFixedHeight(130)
        self.input_field.setAcceptRichText(False)
        self.input_field.textChanged.connect(self.adjust_input_field_height)
        self.input_field.textChanged.connect(self.check_and_send)
        self.input_field.setContentsMargins(0, 0, 0, 0)
        self.input_field.setStyleSheet("border: none;")
        self.input_field.setFocusPolicy(Qt.StrongFocus)  # 设置焦点策略

        # 选择文件按钮
        file_button = PushButton("选择文件")
        file_button.setIcon(FluentIcon.FOLDER_ADD)
        file_button.clicked.connect(self.openFileDialog)

        # 发送按钮
        send_button = PushButton("发送（Ctrl+Enter）")
        send_button.clicked.connect(self.send_message)
        send_button.setStyleSheet(
            "background-color: rgb(235, 233, 233); "
            "color: green; "
            "border-radius: 5px; "
            "border: none; "
            "padding: 5px 10px;"
        )

        # 使用水平布局来使发送按钮靠右
        button_layout = QHBoxLayout()
        button_layout.setSpacing(0)
        button_layout.addWidget(file_button)
        button_layout.addStretch()
        button_layout.addWidget(send_button)

        layout.addWidget(self.input_field, stretch=1)  # 使输入框占据大部分空间
        layout.addLayout(button_layout)
        # layout.addStretch()  # 伸展空间

    def check_and_send(self):
        text = self.input_field.toPlainText().strip()
        if text.startswith("file:///"):
            self.send_message()

    @Slot()
    def send_message(self):
        text = self.input_field.toPlainText().strip()
        if text:
            self.message_sent.emit(text)
            self.input_field.clear()
            self.input_field.setFixedHeight(60)

    def openFileDialog(self):
        # 打开文件选择对话框
        options = QFileDialog.Options()
        file_name, _ = QFileDialog.getOpenFileName(
            self,
            "选择文件",
            "",
            "所有文件 (*);;图像文件 (*.png *.jpg *.jpeg);;视频文件 (*.mp4 *.avi *.mov);;文档文件 (*.pdf *.txt *.doc *.docx *.ppt *.pptx *.xls *.xlsx)",
            options=options
        )
        if file_name:
            file_name = "file:///" + file_name
            # 将选中的文件路径显示在输入框中
            self.input_field.setText(file_name)

    def adjust_input_field_height(self):
        doc = self.input_field.document()
        height = doc.size().height() + 2
        if height > 60:
            height = 60
        self.input_field.setFixedHeight(height)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Return and not (event.modifiers() & Qt.ShiftModifier):  # 检查是否按下了 Enter 键且未按 Shift 键
            self.send_message()
            event.accept()  # 阻止默认的换行操作
        elif event.key() == Qt.Key_Return and (event.modifiers() & Qt.ControlModifier):  # 检查是否按下了 Ctrl+Enter
            self.input_field.insertPlainText("\n")
            event.accept()  # 阻止默认的换行操作
        else:
            super().keyPressEvent(event)


class ChatWindow(QWidget):
    signal_message_send = Signal(int, str, str)

    def __init__(self, index, username, avatar, friend_index, friend_data, parent=None):
        super().__init__(parent)
        self.index = index
        self.username = username
        self.from_username = friend_data["UserName"]
        self.remark_name = friend_data["RemarkName"]
        self.nick_name = friend_data["NickName"]
        self.avatar = avatar
        self.messages = []

        self.init_ui()

    def init_ui(self):
        main_layout = QVBoxLayout(self)
        main_layout.setSpacing(0)  # 减少间距
        self.setLayout(main_layout)

        # 设置背景颜色
        self.setStyleSheet("background-color: rgb(245, 245, 245);")

        # Chat Area
        self.chat_area = QScrollArea()
        self.chat_area.setWidgetResizable(True)
        self.chat_area.setFrameShape(QScrollArea.NoFrame)  # 移除边框
        self.chat_area.setContentsMargins(0, 0, 0, 0)  # 设置边距为 0
        self.chat_widget = QWidget()
        self.chat_layout = QVBoxLayout(self.chat_widget)
        self.chat_layout.setSpacing(0)  # 减少间距
        self.chat_area.setWidget(self.chat_widget)
        self.chat_layout.addStretch()  # 伸展空间

        # 显示好友备注名
        if self.remark_name:
            self.remark_label = QLabel(self.remark_name)
        else:
            self.remark_label = QLabel(self.nick_name)
        self.remark_label.setAlignment(Qt.AlignCenter)  # 居中显示
        self.remark_label.setStyleSheet("font-size: 16px; color: black;")  # 设置字体大小和颜色

        # 将备注名标签添加到主布局的顶部中间位置
        main_layout.addWidget(self.remark_label, alignment=Qt.AlignHCenter)

        # 定义滚动条的样式
        scrollbar_style = """
                    QScrollBar:vertical {
                        border: none;
                        background: transparent;
                        width: 5px;
                        opacity: 0.0;
                        border-radius: 20px;
                    }
                    QScrollBar:hover:vertical {
                        opacity: 1.0;
                    }
                    QScrollBar::handle:vertical {
                        background: #aeabaa;
                        min-height: 20px;
                    }
                    QScrollBar::add-line:vertical {
                        height: 0px;
                    }
                    QScrollBar::sub-line:vertical {
                        height: 0px;
                    }
                    QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
                        border: none;
                        width: 1px;
                        height: 1px;
                        background: none;
                    }
                    QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
                        background: none;
                    }
                """
        # 应用样式
        self.setStyleSheet(scrollbar_style)

        # 添加分割线
        line = QFrame()
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        line.setStyleSheet("color: gray;")  # 设置分割线颜色

        # Input Field
        self.input_widget = MsgInput()
        self.input_widget.message_sent.connect(self.on_message_sent)

        main_layout.addWidget(self.chat_area)
        main_layout.addWidget(line)  # 添加分割线
        main_layout.addWidget(self.input_widget)
        # 设置伸展因子
        main_layout.setStretchFactor(self.chat_area, 3)
        main_layout.setStretchFactor(self.input_widget, 1)
        main_layout.setContentsMargins(0, 0, 0, 0)

        main_layout.addStretch()  # 伸展空间

    @Slot(str)
    def on_message_sent(self, message):
        """
        此处发送信号到`itchat`那里，调用`itchat.send`
        """
        # 向主界面发送消息内容
        self.signal_message_send.emit(self.index, self.from_username, message)
        # 在聊天框中显示消息内容
        self.add_message(self.username, self.avatar, message, "1")
        # self.scroll_to_bottom()

    def add_message(self, username, avatar, message, is_outgoing):
        """
        向聊天框中添加一条消息
        """
        is_outgoing = int(is_outgoing)
        timestamp = QDateTime.currentDateTime().toString("HH:mm:ss")

        # 检查消息是否已存在
        # if any(msg["msg"] == message and msg["is_outgoing"] == is_outgoing for msg in self.messages):
        #     return

        if is_outgoing == 1:
            bubble = MessageBubble(is_outgoing, self.avatar, message, timestamp)
            self.chat_layout.addWidget(bubble)
        elif is_outgoing == 0:
            bubble = MessageBubble(is_outgoing, avatar, message, timestamp)
            self.chat_layout.addWidget(bubble)
        self.messages.append({"username": username, "avatar": avatar, "msg": message, "is_outgoing": is_outgoing})
        self.scroll_to_bottom()

    def scroll_to_bottom(self):
        self.chat_area.verticalScrollBar().setValue(
            self.chat_area.verticalScrollBar().maximum()
        )

    # def showEvent(self, event):
    #     super().showEvent(event)
    #     self.load_messages()

    # def load_messages(self):
    #     for msg in self.messages:
    #         self.add_message("1", msg["msg"])
    # self.scroll_to_bottom()

    def receive_message(self, data):
        """接收一条新消息并添加到聊天记录中"""
        username = data["UserName"]
        avatar = data["Avatar"]
        is_outgoing = data["Msg"]["is_outgoing"]
        message = data["Msg"]["content"]
        if message == "" or message == " ":
            pass
        else:
            self.messages.append({"username": username, "avatar": avatar, "msg": message, "is_outgoing": is_outgoing})
            self.add_message(username, avatar, message, is_outgoing)
        # self.scroll_to_bottom()


if __name__ == "__main__":
    app = QApplication(sys.argv)

    chat_window = ChatWindow({
        "UserName": "@840a6344ebd40b8cf40f7897b76d34a0384964d31447cc729b295cb86155abe2",
        "Avatar": "./downloads/head images\\@840a6344ebd40b8cf40f7897b76d34a0384964d31447cc729b295cb86155abe2.jpg",
        "NickName": "小调气",
        "RemarkName": "C刘",
        "Msg": {
            "is_outgoing": "1",
            "type": "text",
            "content": "你还哦你哈",
            "time": "2023-07-07 12:00:00"
        }
    })
    chat_window.show()
    chat_window.receive_message("0", "你好")
    sys.exit(app.exec_())
